package com.jjc.android.net

import com.jjc.android.UserManager
import com.jjc.android.activity.LoginActivity
import com.jjc.android.base.BaseActivity
import com.jjc.android.entity.LzyResponse
import com.jjc.android.util.GlobalActivityStack
import com.hjq.toast.ToastUtils
import com.jjc.android.App
import com.jjc.android.Constants
import com.jjc.android.R
import com.jjc.android.util.MultiLanguageUtil
import com.lzy.okgo.callback.AbsCallback
import com.lzy.okgo.model.Response
import com.lzy.okgo.request.base.Request
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

abstract class SimpleHttpCallback<T>(private val isToastError:Boolean = true,private val activity:BaseActivity? = null,private val isThird:Boolean=false,private var type: Type? = null,private val clazz: Class<T>? = null) : AbsCallback<T>(){


    override fun onSuccess(response: Response<T>) {
        activity?.hideLoadingDialog()
        val t = response.body()
        if (t != null) {
            if(t is LzyResponse<*>){
                if(t.isOk){
                    onCallSuccess(t)
                }else if(t.code==401||(!t.msg.isNullOrEmpty()&&t.msg == "访问拒绝，令牌无效")){
                    if(isThird){
                        onCallError(t)
                    }else{
                        tokenUnValid()
                    }

                }else{
                    onCallError(t)
                }
            }else{
                onCallSuccess(t)
            }
        } else {
            onCallError("Http Error")
        }
    }

    private fun tokenUnValid(){
        if(UserManager.isLogin()){
            ToastUtils.show(App.getContext().getString(R.string.login_unvalid_txt))
            UserManager.logout{
                GlobalActivityStack.startAndFinishOthers(LoginActivity::class.java)
            }
        }
    }

    abstract fun onCallSuccess(response: T)

    open fun onCallError(error: LzyResponse<*>){
        onCallError(error.msg)
    }

    open fun onCallError(error: String?){
        if(isToastError){
            ToastUtils.show(error)
        }
    }

    override fun onError(response: Response<T>) {
        super.onError(response)
        activity?.hideLoadingDialog()
        if(response.code()==401){
            if(isThird){
//                onCallError(response.exception.message!!)
                onCallError(App.getContext().getString(R.string.net_error_later_retry))
            }else{
                tokenUnValid()
            }

        }else{
//            onCallError(response.exception.message!!)
            onCallError(App.getContext().getString(R.string.net_error_later_retry))
        }
    }

    override fun onStart(request: Request<T, out Request<*, *>?>?) {
        super.onStart(request)
        activity?.showLoadingDialog()
        if(!isThird&&UserManager.isLogin()){
            if(request?.url?.startsWith(Constants.ONTUOTU_BASE_URL)==true){
                request?.headers("Authorization",UserManager.userInfo().tuoTuToken)
            }else{
                request?.headers("Authorization",UserManager.userToken())
            }

        }
        if(request?.url?.startsWith(Constants.BASE_URL)==true){
            request.headers("Accept-Language",if(MultiLanguageUtil.getInstance().isEnglish) "en_US" else "zh_CN")
        }

        // 主要用于在所有请求之前添加公共的请求头或请求参数
        // 例如登录授权的 token
        // 使用的设备信息
        // 可以随意添加,也可以什么都不传
        // 还可以在这里对所有的参数进行加密，均在这里实现
//        request.headers("header1", "HeaderValue1")//
//                .params("params1", "ParamsValue1")//
//                .params("token", "3215sdf13ad1f65asd4f3ads1f");
    }

    override fun onCacheSuccess(response: Response<T>) {
        onSuccess(response)
    }

    /**
     * 该方法是子线程处理，不能做ui相关的工作
     * 主要作用是解析网络返回的 response 对象,生产onSuccess回调中需要的数据对象
     * 这里的解析工作不同的业务逻辑基本都不一样,所以需要自己实现,以下给出的时模板代码,实际使用根据需要修改
     */
    @Throws(Throwable::class)
    override fun convertResponse(response: okhttp3.Response?): T {
        // 重要的事情说三遍，不同的业务，这里的代码逻辑都不一样，如果你不修改，那么基本不可用
        // 重要的事情说三遍，不同的业务，这里的代码逻辑都不一样，如果你不修改，那么基本不可用
        // 重要的事情说三遍，不同的业务，这里的代码逻辑都不一样，如果你不修改，那么基本不可用

        //详细自定义的原理和文档，看这里： https://github.com/jeasonlzy/okhttp-OkGo/wiki/JsonCallback
        if (type == null) {
            type = if (clazz == null) {
                val genType = javaClass.genericSuperclass
                (genType as ParameterizedType).actualTypeArguments[0]
            } else {
                val convert = JsonConvert(clazz)
                return convert.convertResponse(response)
            }
        }
        val convert = JsonConvert<T>(type)
        return convert.convertResponse(response)
    }
}